package com.yuan.blog.listener;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.yuan.blog.constatns.RedisKey;
import com.yuan.blog.dto.EmailDto;
import com.yuan.blog.entity.EmailErrorEntity;
import com.yuan.blog.service.IEmailErrorService;
import com.yuan.blog.utils.MailUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.mail.MessagingException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Date;

@Component
@Slf4j
public class EmailQueueListener {

    @Autowired
    private IEmailErrorService emailErrorService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @RabbitListener(queues = "email-queue")
    public void consumerMsg(EmailDto emailDto, Channel channel, Message message) {
        log.debug("邮箱服务开始发送邮件:{}", emailDto);
        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        try {
            // 邮件发送
            sendMsg(emailDto);

            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            log.error("邮件发送失败了:", e);

            // 把发送失败的邮件记录到MySQL中，给MQServler继续应答ACK===》持久化
            int insert = saveDB(emailDto);
            if (insert > 0) {
                try {
                    log.debug("邮件入库成功");
                    channel.basicAck(deliveryTag, false);
                    //删除缓存中的错误邮件数据
                    redisTemplate.delete(RedisKey.EMAIL_ERROR_KEY);
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            } else {
                try {
                    log.debug("邮件入库失败");
                    channel.basicNack(deliveryTag, false, true);
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        }
    }

    private Integer saveDB(EmailDto emailDto) {
        EmailErrorEntity entity = new EmailErrorEntity();
        entity.setCreateTime(new Date());
        entity.setStatus(1);
        entity.setEmailText(JSON.toJSONString(emailDto));
        boolean save = emailErrorService.save(entity);
        Integer id = entity.getId();
        redisTemplate.opsForSet().add(RedisKey.EMAIL_ID_KEY,id.toString());
        return save ? 1 : 0;
    }

    private void sendMsg(EmailDto emailDto) throws MessagingException {
        int status = 0;
        int count = 3;
        do {
            status = MailUtil.sendSimpleMail(emailDto);
            //如果发送成功，退出循环
            if (status == 1) {
                break;
            }
            count--;
        } while (count > 0);

    }
}
